1 解析默认bean标签
在上一篇博客中,最后调用了parseBeanDefinitions()方法,bean标签的解析便是在该方法内进行的,参照以下代码
DefaultBeanDefinitionDocumentReader.java
这里我们先讲解解析默认标签分支也就是,parseDefaultElement()方法
DefaultBeanDefinitionDocumentReader.java
在processBeanDefinition中主要进行以下业务逻辑处理:
- 首先委托BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefintionHolder类型的实例bdHolder。经过这个方法后,bdHolder实例已经包含我们配置文件中配置的各种属性了,例如class、name、id、alias
- 当返回bdHolder不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行解析
- 解析完成后,需要对解析后的bdHolder进行注册,同样,注册操作委托给了BeanDefinitionReaderUtils的registerBeanDefinition方法
- 最后发出响应时间,通知相关的监听器,这个bean已经加载完成了
1.1 委托BeanDefinitionParserDelegate的parseBeanDefinitionElement方法进行元素解析
BeanDefinitionParserDelegate.java
以上便是对spring的默认便签解析的全过程,当前方法只提取了id和name属性,对于其余标签的解析是通过parseBeanDefinitionElement方法来完成的,其主要业务逻辑:
- 提取元素的id以及name属性
- 通过parseBeanDefinitionElement方法解析其他标签属性,并将这些属性封装在GenericBeanDefinition类型实例中
- 如果检测到bean没有指定beanName,name使用默认规则为此Bean生成beanName
- 将得到的GenericBeanDefinition类型实例封装到BeanDefinitionHolder类型实例中
1.1.1 BeanDefinition类型
BeanDefinition是一个接口,在spring中存在三种实现:RootBeanDefinition、childBeanDefinition、GenericBeanDefinition。三种实现均继承了AbstractBeanDefinition。其中BeanDefinition是配置文件
1.1.2 解析标签属性
BeanDefinitionParserDelegate.java
2 解析默认标签中的自定义标签元素
上述章节讲解了如何对bean标签进行解析,接下来回到processBeanDefinition()方法,代码如下:
这里的decorateBeanDefinitionIfRequired就是负责对默认标签内部的自定义类型标签解析的方法,可以看下其内部的业务逻辑
BeanDefinitionParserDelegate.java
最终的标签解析是在decorateIfRequired中完成地,可以看到主要有以下业务逻辑
- 获取自定义标签的命名空间
- 对非默认标签进行修饰
- 根据命名空间找到对应的处理器并进行解析
3 注册被解析的BeanDefinition
对于配置文件,解析和装饰完成后就可以对得到的beanDefinition进行注册,注册是在DefaultBeanDefinitionDocumentReader中的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());这个行代码中进行的
DefaultBeanDefinitionDocumentReader.java
BeanDefinitionReaderUtils.java
通过registerBeanDefinition可以看出,BeanDefinition的注册分为用beanname注册和利用alias进行注册,我们再看看 实现了BeanDefinitionRegistry接口的DefaultListableBeanFactory类的registerBeanDefinition方法,也是用beanName进行注册的业务逻辑
这个方法主要完成以下几个主要事项
- 对AbstractBeanDefinition进行校验,这里的校验并非xml文档格式的校验,而是对于AbstractBeanDefinition的methodOverrides属性的校验
- 对beanName已经注册的情况的处理,如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖
- 加入map缓存
- 清楚解析之前留下的对应的beanName的缓存